﻿using OverStore.Configuration.Validation;
using OverStore.Runtime.OverStoreContext;
using OverStore.Runtime.ObjectRepository;
using OverStore.Runtime.ObjectRepository.CallbackManager;
using OverStore.Runtime.ObjectRepository.DeferredLoader;

namespace OverStore.Configuration.ObjectRepository
{

    /// <summary>
    /// Base class contains configuration properties for all types of repository.
    /// </summary>
    /// <typeparam name="TInstance">The type of the instance.</typeparam>
    public abstract class RepositoryConfigurationBase<TInstance> : IComponentConfiguration<IRepository<TInstance>>,
        IComponentConfiguration<IRepositoryBase>, ISupportValidation
        where TInstance : class
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="RepositoryConfigurationBase&lt;TInstance&gt;"/> class.
        /// </summary>
        protected RepositoryConfigurationBase()
        {
        }

        /// <summary>
        /// Get or set configuration for callback manager uses for notify instance about 
        /// persisting operation are performed on it.
        /// </summary>
        public IComponentConfiguration<ICallbackManager<TInstance>> CallbackManager { get; set; }

        /// <summary>
        /// Get or set lazy loader for objct repository.
        /// 
        /// By default, ObjectLazyLoader is used.
        /// </summary>
        public IComponentConfiguration<IDeferredLoader<TInstance>> DeferredLoader { get; set; }

        /// <summary>
        /// Creates the new instance of <see cref="IRepository{TInstance}"/>.
        /// </summary>
        /// <param name="context">The current context provides set of services may be used by <see cref="IRepository{TInstance}"/> instance.</param>
        /// <returns>
        /// The new instance of <see cref="IRepository{TInstance}"/> type.
        /// </returns>
        public abstract IRepository<TInstance> CreateComponent(IOverStoreContext context);

        IRepositoryBase IComponentConfiguration<IRepositoryBase>.CreateComponent(IOverStoreContext context)
        {
            return CreateComponent(context);
        }

        /// <summary>
        /// Perform component validation. Method should validate only
        /// component configuration itself, not sub components.
        /// If configuration is valid, null result should returns.
        /// </summary>
        /// <returns>
        ///     <see cref="T:OverStore.Configuration.ValidationResults"/> describes errors found in component configuration.
        /// </returns>
        public virtual ValidationResult Validate()
        {
            return new ValidationResult(this)
                  .ValidateToNestedResult(CallbackManager)
                  .ValidateToNestedResult(DeferredLoader);
        }
    }
}
